package com.yangdada.utils;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import lombok.extern.slf4j.Slf4j;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.temporal.WeekFields;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @author ccwx
 * @description 时间工具类
 * @date 2022-06-12 12:27
 **/
@Slf4j
public class DateUtil {

    /**
     * 时间格式化
     */
    public static final String DATE_FORMAT = "yyyy-MM-dd";

    /**
     * 时间格式化
     */
    public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";

    /**
     * 时间格式化
     */
    public static final String DATE_TIME_FORMAT02 = "yyyyMMddHHmmss";

    /**
     * 一天的毫秒数
     */
    public static final double DAY_OF_TIMEMILLIS = 1000 * 3600 * 24;

    /**
     * 天数之差
     *
     * @param endDate
     * @return
     */
    public static int timeDiffDay(Date endDate) {
        if (endDate == null) {
            return 0;
        }
        Date current = new Date();
        if (endDate.getTime() - current.getTime() <= 0) {
            return 0;
        }
        Double result = (endDate.getTime() - current.getTime()) / DAY_OF_TIMEMILLIS;
        Double dayBetween = Math.ceil(result);
        return dayBetween.intValue();
    }

    /**
     * 格式化 日期
     *
     * @param date
     * @param format
     * @return
     */
    public static String formatDate(Date date, String format) {
        if (StringUtils.isNotBlank(format)) {
            SimpleDateFormat sdf = new SimpleDateFormat(format);
            return sdf.format(date);
        }
        return "";
    }

    /**
     * 获取全日期格式
     *
     * @param date
     * @return
     */
    public static String getWholeDate(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat(DateUtil.DATE_TIME_FORMAT);
        return sdf.format(date);
    }

    /**
     * 时间转换
     *
     * @return
     */
    public static String getWholeDateForNow() {
        SimpleDateFormat sdf = new SimpleDateFormat(DateUtil.DATE_TIME_FORMAT);
        return sdf.format(new Date());
    }

    /**
     * 日期转字符串
     * 按dateFormat格式返回当前日期的字符串值
     *
     * @param currentDate 当前日期
     * @param dateFormat  要转换的格式
     * @return String
     */
    public static String dateToStr(Date currentDate, String dateFormat) {
        SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
        if (null != currentDate) {
            return sdf.format(currentDate);
        } else {
            return sdf.format(new Date());
        }
    }

    /**
     * 日期转换成字符串
     *
     * @param date
     * @return
     */
    public static String getFormatDate(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat(DateUtil.DATE_FORMAT);
        return sdf.format(date);
    }

    /**
     * 字符串转date
     *
     * @param dataStr
     * @return
     */
    public static Date getStringToDate(String dataStr,String dateFormat) {
        SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
        try {
            return sdf.parse(dataStr);
        } catch (ParseException ex) {
            log.error("data format fail,{}", ex);
            return null;
        }
    }

    /**
     * 字符串转date
     *
     * @param dataStr
     * @return
     */
    public static Date convertStringToYmdhms(String dataStr) {
        SimpleDateFormat sdf = new SimpleDateFormat(DATE_TIME_FORMAT);
        try {
            return sdf.parse(dataStr);
        } catch (ParseException ex) {
            log.error("data format fail,{}", ex);
            return null;
        }
    }

    /**
     * 当前日期加上天数后的日期
     *
     * @param num 为增加的天数
     * @return
     */
    public static Date plusDay(int num, Date date) {
        Calendar ca = Calendar.getInstance();
        //设置起时间
        ca.setTime(date);
        // num为增加的天数，可以改变的
        ca.add(Calendar.DATE, num);
        return ca.getTime();
    }

    /**
     * 把时间类型转化为规定格式的字符串
     * "yyyy-MM-dd hh:MM:ss"
     *
     * @param date 时间
     * @return 格式化以后的时间字符串
     */
    public static String convertDateToYmdhms(Date date) {
        if (date == null) {
            return null;
        }
        SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return f.format(date);
    }

    /**
     * 加几年
     *
     * @param d    当前时间
     * @param diff 间隔年
     * @return
     */
    public static Date addYear(Date d, int diff) {
        Calendar c = Calendar.getInstance();
        c.setTime(d);
        c.add(Calendar.YEAR, diff);
        return c.getTime();
    }

    /**
     * 添加月
     *
     * @param d
     * @param diff
     * @return
     */
    public static Date addMonth(Date d, int diff) {
        Calendar c = Calendar.getInstance();
        c.setTime(d);
        c.add(Calendar.MONTH, diff);
        return c.getTime();
    }

    /**
     * 加天数
     *
     * @param d
     * @param diff
     * @return
     */
    public static Date addDate(Date d, int diff) {
        Calendar c = Calendar.getInstance();
        c.setTime(d);
        c.add(Calendar.DATE, diff);
        return c.getTime();
    }

    /**
     * 增加diff小时
     *
     * @param d
     * @param diff
     * @return
     */
    public static Date addHour(Date d, int diff) {
        Calendar c = Calendar.getInstance();
        c.setTime(d);
        c.add(Calendar.HOUR_OF_DAY, diff);
        return c.getTime();
    }

    /**
     * 增加diff秒
     *
     * @param d
     * @param diff
     * @return
     */
    public static Date addSecond(Date d, Integer diff) {
        Calendar c = Calendar.getInstance();
        c.setTime(d);
        c.add(Calendar.SECOND, diff);
        return c.getTime();
    }

    /**
     * String-->date String转Date，2000-01-01 22:22:22
     *
     * @param dateStr
     * @return
     */
    public static Date convertStringToDate(String dateStr) {
        return convertStringToDate(dateStr, "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 解析日期字符串为Date
     *
     * @param dateStr
     * @param format
     * @return
     */
    public static Date convertStringToDate(String dateStr, String format) {
        SimpleDateFormat f = new SimpleDateFormat(format);
        if (StringUtils.isBlank(dateStr)) {
            return null;
        }
        try {
            return f.parse(dateStr);
        } catch (ParseException e) {
            log.error("转化为时间失败", e);
        }
        return null;
    }

    /**
     * 时间转换
     *
     * @param date
     * @param formatStr
     * @return
     */
    public static String convertDateToStr(Date date, String formatStr) {
        if (date == null) {
            return null;
        }
        SimpleDateFormat f = new SimpleDateFormat(formatStr);
        return f.format(date);
    }

    /**
     * 获取今天的最后时间 23:59:59
     */
    public static String getLastTimeOfToday() {
        Calendar todayEnd = Calendar.getInstance();
        todayEnd.set(Calendar.HOUR_OF_DAY, 23);
        todayEnd.set(Calendar.MINUTE, 59);
        todayEnd.set(Calendar.SECOND, 59);
        todayEnd.set(Calendar.MILLISECOND, 999);
        return convertDateToYmdhms(todayEnd.getTime());
    }

    /**
     * 获取今天的开始时间 00:00:00
     *
     * @return
     */
    public static String getStartTimeOfToday() {
        Calendar todayStart = Calendar.getInstance();
        todayStart.set(Calendar.HOUR_OF_DAY, 0);
        todayStart.set(Calendar.MINUTE, 0);
        todayStart.set(Calendar.SECOND, 0);
        todayStart.set(Calendar.MILLISECOND, 0);
        return convertDateToYmdhms(todayStart.getTime());
    }

    /**
     * 时间戳转格式化后的时间字符串
     * 1582188242227--》2020-02-20 11:01:01
     *
     * @param seconds
     * @param format
     * @return
     */
    public static String timeStamp2Date(String seconds, String format) {
        if (seconds == null || seconds.isEmpty()) {
            return "";
        }
        if (format == null || format.isEmpty()) {
            format = "yyyy-MM-dd HH:mm:ss";
        }
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(Long.valueOf(seconds));
    }

    /**
     * 格式化时间字符串转时间戳
     * "2020-02-20 17:24:06"-----》1582190646000
     *
     * @param dateStr
     * @param format
     * @return
     */
    public static String date2TimeStamp(String dateStr, String format) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(format);
            return String.valueOf(sdf.parse(dateStr).getTime());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 获取两个日期字符串之间的日期集合
     *
     * @param startTime:String
     * @param endTime:String
     * @return list:yyyy-MM-dd
     */
    public static List<String> getBetweenDate(String startTime, String endTime) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        // 声明保存日期集合
        List<String> list = new ArrayList<String>();
        try {
            // 转化成日期类型
            Date startDate = sdf.parse(startTime);
            Date endDate = sdf.parse(endTime);

            //用Calendar 进行日期比较判断
            Calendar calendar = Calendar.getInstance();
            while (startDate.getTime() <= endDate.getTime()) {
                // 把日期添加到集合
                list.add(sdf.format(startDate));
                // 设置日期
                calendar.setTime(startDate);
                //把日期增加一天
                calendar.add(Calendar.DATE, 1);
                // 获取增加后的日期
                startDate = calendar.getTime();
            }
        } catch (ParseException e) {
            log.error("getBetweenDate error", e);
        }
        return list;
    }


    /**
     * 获取两个日期之间所有的月份集合
     *
     * @param startTime
     * @param endTime
     * @return：YYYY-MM
     */
    public static List<String> getMonthBetweenDate(String startTime, String endTime) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        // 声明保存日期集合
        List<String> list = new ArrayList<String>();
        try {
            // 转化成日期类型
            Date startDate = sdf.parse(startTime);
            Date endDate = sdf.parse(endTime);

            //用Calendar 进行日期比较判断
            Calendar calendar = Calendar.getInstance();
            while (startDate.getTime() <= endDate.getTime()) {
                // 把日期添加到集合
                list.add(sdf.format(startDate));
                // 设置日期
                calendar.setTime(startDate);
                //把日期增加一天
                calendar.add(Calendar.MONTH, 1);
                // 获取增加后的日期
                startDate = calendar.getTime();
            }
        } catch (ParseException e) {
            log.error("getMonthBetweenDate error", e);
        }
        return list;
    }

//
//    /**
//     * 获取两个日期之间所有的月份集合
//     *
//     * @param startTime
//     * @param endTime
//     * @return：YYYY-MM
//     */
//    public static List<String> getWeekBetweenDate(String startTime, String endTime) {
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
//        // 声明保存日期集合
//        List<String> list = new ArrayList<String>();
//        try {
//            // 转化成日期类型
//            Date startDate = sdf.parse(startTime);
//            Date endDate = sdf.parse(endTime);
//
//            //用Calendar 进行日期比较判断
//            Calendar calendar = Calendar.getInstance();
//            while (startDate.getTime() <= endDate.getTime()) {
//                // 把日期添加到集合
//                list.add(sdf.format(startDate));
//                // 设置日期
//                calendar.setTime(startDate);
//                //把日期增加一天
//                calendar.add(Calendar.WEEK_OF_YEAR, 1);
//                // 获取增加后的日期
//                startDate = calendar.getTime();
//            }
//        } catch (ParseException e) {
//            log.error("getWeekBetweenDate error", e);
//        }
//        return list;
//    }

    /**
     * @Description: 获取两个日期之间的 周集合
     * @Author:
     * @createTime:
     */
    public static List<String> getWeekBetweenDate(String dateStr1, String dateStr2) {
        List<String> list = new ArrayList<>();
        try {
            list = getWeekBetweenDateNoSort(dateStr1, dateStr2);
            //兼容排序 对个位数处理：1 --> 01
            for (int i = 0; i < list.size(); i++) {
                String[] split1 = list.get(i).split("-");
                if (split1[1].length() == 1) {
                    split1[1] = "0" + split1[1];
                    list.set(i, split1[0] + "-" + split1[1]);
                }
            }
        } catch (Exception e) {
            log.error("getWeeks error", e);
        }
        return list;
    }

    private static void extracted(String dateStr1, String dateStr2, List<String> list) {
        //存在2021-1周是按2021-01-01去定位的情况
        if (!list.get(list.size() - 1).equals(dateStr2)) {
            //小于--》添加
            if (list.get(list.size() - 1).compareTo(dateStr2) < 0) {
                list.add(dateStr2);
            }
            //大于--》删除
            if (list.get(list.size() - 1).compareTo(dateStr2) > 0) {
                list.remove(list.get(list.size() - 1));
            }
        }

        if (!list.get(0).equals(dateStr1)) {
            //小于--》删除
            if (list.get(0).compareTo(dateStr1) < 0) {
                list.remove(list.get(0));
            }
            //大于--》添加
            if (list.get(0).compareTo(dateStr1) > 0) {
                list.add(list.get(0));
            }
        }
    }


    /**
     * @Description: 获取两个日期之间的 周集合
     * @Author:
     * @createTime:
     */
    public static List<String> getWeekBetweenDateNoSort(String dateStr1, String dateStr2) {
        List<String> list = new ArrayList<>();
        try {
            String[] split = dateStr1.split("-");
            Calendar cal = Calendar.getInstance();
            cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
            cal.set(Calendar.YEAR, Integer.parseInt(split[0]));
            cal.set(Calendar.WEEK_OF_YEAR, Integer.parseInt(split[1]));
            cal.setMinimalDaysInFirstWeek(4);
            Date time = cal.getTime();

            String[] split2 = dateStr2.split("-");
            Calendar cal2 = Calendar.getInstance();
            cal2.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
            cal2.set(Calendar.YEAR, Integer.parseInt(split2[0]));
            cal2.set(Calendar.WEEK_OF_YEAR, Integer.parseInt(split2[1]));
            cal2.setMinimalDaysInFirstWeek(4);
            Date time2 = cal2.getTime();

            LocalDate start = time.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            LocalDate end = time2.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

            // 初始化
            // WeekFields weekFields = WeekFields.of(DayOfWeek.MONDAY,1);
            WeekFields weekFields = WeekFields.ISO;
            while (start.compareTo(end) <= 0) {
                int year = start.getYear();
                int week = start.get(weekFields.weekOfWeekBasedYear());
                //对年头/尾的周进行转换
                if (start.getDayOfYear() > 7 && week == 1) {
                    year++;
                }
                if (start.getDayOfYear() < 7 && week > 1) {
                    year--;
                }
                list.add(year + "-" + week);
                start = start.plusWeeks(1);
            }
            //处理头尾数据
            extracted(dateStr1, dateStr2, list);
        } catch (Exception e) {
            log.error("getWeeks error", e);
        }
        return list;
    }

    public static int getLastDayOfMonth(String queryYear, String queryMonth) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Integer.parseInt(queryYear), Integer.parseInt(queryMonth), 1);
        calendar.add(Calendar.DAY_OF_MONTH, -1);
        return calendar.get(Calendar.DAY_OF_MONTH);
    }
}
